热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JavaNIOBuffer详解及其优势与局限性分析

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Java Nio 的Buffer和优缺点相关的知识,希望对你有一定的参考价值。 Java Nio 的Buffer 在数据传输的时候,我们

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Java Nio 的Buffer和优缺点相关的知识,希望对你有一定的参考价值。



Java Nio 的Buffer

在数据传输的时候,我们会用到缓冲区。Java NIO中的Buffer用于和NIO通道进行交互。如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的。缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存。Java的NIO 为我们提供了原生的八种缓冲区实现,对应着Java 的七种基本类型和MappedByteBuffer。

Java NIO 有以下Buffer类型


  • ByteBuffer
  • MappedByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

Java中的这些Buffer已经足够我们使用,但是这些确实基本的操作,在复杂的应用的时候就需要我们自己去封装。由此我们可以知道netty为什么对java 的nio进行封装了。


  1. 原生的Buffer,在创建缓存区的时候分指定分配的空间。一旦创建,就不能动态的扩展。
  2. 原生的Buffer中只有一个位置标记位,我们能修改通过操作这个标记为来实现访问和存取容易出错。
  3. Buffer简单功能的函数,需要我们自己实现复杂函数。

操作位置的函数

对缓冲区的读写操作首先要知道缓冲区的下限、上限和当前位置。下面这些变量的值对Buffer类中的某些操作有着至关重要的作用:


  1. limit:所有对Buffer读写操作都会以limit变量的值作为上限。
  2. position:代表对缓冲区进行读写时,当前游标的位置。
  3. capacity:代表缓冲区的最大容量(一般新建一个缓冲区的时候,limit的值和capacity的值默认是相等的)。

clear方法将缓冲区清空,一般是在重新写缓冲区时调用。

public final Buffer clear()
position = 0; //重置当前读写位置
limit = capacity;
mark = -1; //取消标记
return this;

反转缓冲区。首先将限制设置为当前位置,然后将位置设置为 0。通常情况下,在准备从缓冲区中读取数据时调用flip方法。

public final Buffer flip()
limit = position;
position = 0;
mark = -1;
return this;

使缓冲区为重新读取已包含的数据做好准备:它使限制保持不变,将位置设置为 0。

public final Buffer rewind()
position = 0;
mark = -1;
return this;

以上三种方法均使用final修饰,java.nio.Buffer的所有子类均使用同一种flip、clear和rewind机制。

这三个方法在源码上就对缓冲区的数据不进行任何修改。

一旦读完了所有的数据,就需要清空缓冲区,让它可以再次被写入。有两种方式能清空缓冲区:调用clear()或compact()方法。clear()方法会清空整个缓冲区。compact()方法只会清除已经读过的数据。任何未读的数据都被移到缓冲区的起始处,新写入的数据将放到缓冲区未读数据的后面。


其他函数


  1. Buffer的分配

    每一个Buffer类都有一个allocate方法。ByteBuffer buf = ByteBuffer.allocate(48);

  2. 向Buffer中写数据

    写数据到Buffer有两种方式:


    1. 从Channel写到Buffer。int bytesRead = inChannel.read(buf); //read into buffer.
    2. 通过Buffer的put()方法写到Buffer里。buf.put(127);
  3. 从Buffer中读取数据

    从Buffer中读取数据有两种方式:


    1. 从Buffer读取数据到Channel。int bytesWritten = inChannel.write(buf);
    2. 使用get()方法从Buffer中读取数据。byte aByte = buf.get();
  4. mark()与reset()方法

    通过调用Buffer.mark()方法,可以标记Buffer中的一个特定position。之后可以通过调用Buffer.reset()方法恢复到这个position。

  5. equals()与compareTo()方法

    可以使用equals()和compareTo()方法比较两个Buffer。

  6. equals()

    当满足下列条件时,表示两个Buffer相等:


    1. 有相同的类型(byte、char、int等)。
    2. Buffer中剩余的byte、char等的个数相等。
    3. Buffer中所有剩余的byte、char等都相同。
      如你所见,equals只是比较Buffer的一部分,不是每一个在它里面的元素都比较。实际上,它只比较Buffer中的剩余元素。
  7. compareTo()方法

    compareTo()方法比较两个Buffer的剩余元素(byte、char等), 如果满足下列条件,则认为一个Buffer“小于”另一个Buffer:


    1. 第一个不相等的元素小于另一个Buffer中对应的元素 。
    2. 所有元素都相等,但第一个Buffer比另一个先耗尽(第一个Buffer的元素个数比另一个少)。

应用举例

public static void main(String[] args) throws IOException
RandomAccessFile aFile = new RandomAccessFile("input/input.txt", "rw");
FileChannel inChannel = aFile.getChannel();
//create buffer with capacity of 48 bytes
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buf); //read into buffer.
while (bytesRead != -1)
buf.flip(); //make buffer ready for read
while(buf.hasRemaining())
System.out.print((char) buf.get()); // read 1 byte at a time

System.out.println("bytesRead = " + bytesRead);
buf.clear();//make buffer ready for writing
bytesRead = inChannel.read(buf);

aFile.close();


参考资料:
网上资料
备注:
转载请注明出处:http://blog.csdn.net/wsyw126/article/details/75208264
作者:WSYW126


推荐阅读
  • 程序连接MySQL数据库的多种方法详解 ... [详细]
  • 在处理Java程序时,中文乱码是一个常见的问题。本文将详细探讨导致中文乱码的原因,并分享有效的解决方案,帮助开发者在实际工作中避免这一问题。通过具体的代码示例和最佳实践,本文旨在提供全面的指导,确保中文字符在不同环境下的正确显示。 ... [详细]
  • 本文通过复旦大学自然语言处理课程中的一个具体案例,详细解析了中文词汇分割技术的实现方法。该案例利用Java编程语言,结合词典和算法模型,展示了如何高效地进行中文文本的词汇分割,为相关研究和应用提供了宝贵的参考。 ... [详细]
  • 利用Java开发百度图片爬虫,实现高效下载功能
    为了满足大量图像素材的需求以支持机器学习项目,本文介绍了一种基于Java语言开发的百度图片爬虫工具,该工具能够高效地抓取并下载百度图片中的资源。文章首先展示了爬虫运行的效果图,并详细阐述了其工作原理和技术实现路径,重点解析了如何通过分析百度图片的网页结构来实现精准抓取。此外,还讨论了在实际应用中可能遇到的问题及解决方案。 ... [详细]
  • Oracle培训(三十七)——深入解析Hibernate第三章:实体关联关系映射详解
    在本节Oracle培训中,我们将深入探讨Hibernate第三章的内容,重点讲解实体关联关系映射的详细知识点。首先,回顾了Hibernate的基本概念和映射基础,随后详细分析了不同类型的实体关联关系,包括一对一、一对多和多对多关系的映射方法及其应用场景。通过具体的示例和代码片段,帮助读者更好地理解和掌握这些复杂的映射技术。此外,还讨论了如何优化关联关系的性能,以及常见的问题和解决方案。 ... [详细]
  • 本文介绍了一个基于C++标准库实现的INI文件读写操作类。该类在现有网络资源的基础上进行了扩展和优化,增加了获取当前可执行文件路径和宽字节与多字节字符串转换的功能。通过这些增强功能,该类能够更好地适应各种应用场景,提高代码的可移植性和健壮性。具体实现细节请参见 `IniFileSTL.h` 文件。 ... [详细]
  • 本文旨在构建一个JavaScript函数,用于对用户输入的电子邮件地址和密码进行有效性验证。该函数将确保输入符合标准格式,并检查密码强度,以提升用户账户的安全性。通过集成正则表达式和条件判断语句,该方法能够有效防止常见的输入错误,同时提供即时反馈,改善用户体验。 ... [详细]
  • 通过采用JSON数据格式,能够高效且精确地获取用户的实时地理位置信息,为各类位置服务应用提供可靠的数据支持。该方法不仅简化了数据交换流程,还提高了地理信息处理的准确性和效率,适用于移动应用、导航系统及物联网设备等多种场景。 ... [详细]
  • Android数组截取技巧及JNI数组交互在仓库构建中的应用分析
    在Android开发中,数组截取技巧和JNI数组交互在仓库构建中的应用具有重要意义。JNI提供了两种主要的数组处理方法:一是生成原生层数组的副本,二是直接通过数组指针进行操作。在进行字符串处理时,如果需要执行其他复杂操作,可以结合这两种方法以提高效率和灵活性。此外,合理利用这些技术可以显著提升应用程序的性能和稳定性。 ... [详细]
  • 在Java NIO中,`ByteBuffer` 的内存分配方式分为 `allocate` 和 `allocateDirect`。前者在JVM堆内存中分配空间,返回 `HeapByteBuffer` 实例,初始位置为0,容量和限制由参数指定。而 `allocateDirect` 则在操作系统本地内存中分配,返回 `DirectByteBuffer`,适用于需要频繁与I/O操作交互的场景,性能更高但管理成本较大。两者在内存管理和性能上各有优劣,选择时需根据具体应用场景权衡。 ... [详细]
  • 深入解析Android中图像资源的内存占用问题及其优化策略
    在Android开发过程中,图像资源的内存占用是一个值得关注的问题。本文将探讨图像内存占用与哪些因素相关,包括设备性能的影响,并提供一系列优化策略,帮助开发者有效管理图像资源,提升应用性能。 ... [详细]
  • 在Java中准确获取字符串长度的方法与技巧解析。首先,通过Eclipse创建一个新的Java项目,项目名称可自定义。完成后,右键点击项目名称,选择新建类。在类中,可以通过调用`String`对象的`length()`方法来统计字符串的长度。此外,还可以利用其他字符串处理库或工具类来实现更复杂的字符串长度计算,例如使用Apache Commons Lang库中的`StringUtils`类,以提高代码的可读性和健壮性。 ... [详细]
  • 本文介绍了如何利用摄像头捕捉图像,并将捕获的图像数据保存为文件。通过详细的代码示例,展示了摄像头调用的具体实现方法,适用于多种应用场景,如安全监控、图像处理等。 ... [详细]
  • OpenCV 2.4.9 源码解析:级联分类器的错误率与尺寸分析 ... [详细]
  • 基于灰度直方图的水果识别系统开发:MATLAB源代码及图形用户界面设计
    基于灰度直方图的水果识别系统开发:MATLAB源代码及图形用户界面设计 ... [详细]
author-avatar
流血的云_-86097
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有